package com.logic.landseaserver.service.impl;

import java.sql.Timestamp;
import java.util.*;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.logic.common.exception.BusinessException;
import com.logic.common.security.SecurityUtils;
import com.logic.common.util.SysUtil;
import com.logic.landseaserver.common.LandseaErrorMessageEnum;
import com.logic.landseaserver.common.VariableChar;
import com.logic.landseaserver.common.config.DingXinConfiguration;
import com.logic.landseaserver.common.enums.MeterTypeEnum;
import com.logic.landseaserver.common.exception.LandseaBusinessException;
import com.logic.landseaserver.common.util.DateUtil;
import com.logic.landseaserver.common.util.WebUtils;
import com.logic.landseaserver.domain.ChangeMeter;
import com.logic.landseaserver.domain.CleanLog;
import com.logic.landseaserver.domain.MeterData;
import com.logic.landseaserver.persistence.read.CleanLogReadMapper;
import com.logic.landseaserver.persistence.read.MeterDataReadMapper;
import com.logic.landseaserver.persistence.write.ChangeMeterWriteMapper;
import com.logic.landseaserver.persistence.write.CleanLogWriteMapper;
import com.logic.landseaserver.persistence.write.MeterDataHistoryWriteMapper;
import com.logic.landseaserver.persistence.write.MeterDataWriteMapper;
import com.logic.landseaserver.service.IMeter;
import com.logic.landseaserver.ws.dto.CleanLogDTO;
import com.logic.landseaserver.ws.request.AchieveDayFreezeEnergyReq;
import com.logic.landseaserver.ws.request.RepairHydropoerDataReq;
import com.logic.landseaserver.ws.response.QueryConsNoListResp;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;


/**
 * @Author: quintina
 * @Date: 2017/5/4
 * @Description: 鼎信电力接口实现类
 */
@Service
public class MeterServiceImpl implements IMeter {


    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private DingXinConfiguration dingXinConfiguration;
    @Autowired
    private MeterDataReadMapper meterDataReadMapper;
    @Autowired
    private MeterDataWriteMapper meterDataWriteMapper;
    @Autowired
    private ChangeMeterWriteMapper changeMeterWriteMapper;
    
    @Autowired
    private MeterDataHistoryWriteMapper meterDataHistoryWriteMapper;
    
    @Autowired
    private CleanLogWriteMapper cleanLogWriteMapper;
    
    @Autowired
    private CleanLogReadMapper cleanLogReadMapper;

    @Override
    public void insertAchieveDayFreezeEnergy(AchieveDayFreezeEnergyReq req) throws BusinessException {
        List<QueryConsNoListResp> list = new ArrayList<>();
        List<Integer> dxPrjs =  meterDataReadMapper.queryDxPrjList();
        if(dxPrjs.size()>0){
            for(Integer prjId : dxPrjs){
                    List<Integer> rooms = meterDataReadMapper.queryDxRooms(prjId);
                    if(rooms.size()>0){
                        StringBuffer rmStr = new StringBuffer();
                        for(Integer roomId:rooms){
                            rmStr.append(roomId+",");
                        }
                        logger.info("insertAchieveDayFreezeEnergy rooms is :"+rmStr.toString());
                        QueryConsNoListResp consNoListResp = new QueryConsNoListResp();
                        consNoListResp.setPrjId(prjId);
                        consNoListResp.setConsNo(rmStr.toString().substring(0,rmStr.toString().length() - 1));
                        list.add(consNoListResp);
                    }
            }
        }

        if (list != null && list.size() > 0) {
            for (QueryConsNoListResp resp : list) {
                if (!StringUtils.isEmpty(resp.getConsNo())) {
                    req.setConsNos(resp.getConsNo().replace(",",";"));
                    Object object = JSONObject.fromObject(achieveDayFreezeEnergy(req));
                    insertDayFreezeEnergy((JSONObject) object, resp.getPrjId());
                }
            }
        }
    }

    @Override
    public String achieveDayFreezeEnergy(AchieveDayFreezeEnergyReq req) throws BusinessException {

        checkObject(req);
        Map<String, String> map = new HashMap<String, String>();
        map.put("consNos", req.getConsNos());
        map.put("dateFrom", req.getDateFrom());
        map.put("dateTo", req.getDateTo());
        map.put("meterType", "1");
        String result = null;
        String url = dingXinConfiguration.getDayFreezeEnergy();
        try {
            result = WebUtils.post(url, map);
        } catch (Exception e) {
            logger.error("achieveDayFreezeEnergy error.", e);
        }
        JSONObject resultObject = JSONObject.fromObject(result);
        return result;
    }

    @Override
    public void batchUpdateMeterData() throws BusinessException {


        String dateFrom = DateUtil.getInstence().convertDate(org.apache.commons.lang3.time.DateUtils.addDays(new Date(), -(Integer.parseInt("3") + 1)));
        String dateTo = DateUtil.getInstence().convertDate(org.apache.commons.lang3.time.DateUtils.addDays(new Date(), -2));
        RepairHydropoerDataReq req = new RepairHydropoerDataReq();
        req.setDateFrom(dateFrom);
        req.setDateTo(dateTo);
        repairMeterData(req);
    }

    @Override
    public void batchInsertFeeDetail(AchieveDayFreezeEnergyReq req) throws BusinessException {
        logger.info("batchInsertFeeDetail start" + new Date());
        Date startDate = DateUtil.getInstence().convertDate(req.getDateFrom());
        Date endDate = DateUtil.getInstence().convertDate(req.getDateTo());
        int days = (int) ((endDate.getTime() - startDate.getTime()) / 86400000);
        endDate = DateUtils.addDays(startDate, 1);
        AchieveDayFreezeEnergyReq param = new AchieveDayFreezeEnergyReq();
        param.setProjectId(req.getProjectId());
        param.setMeterType(req.getMeterType());
        param.setConsNos(req.getConsNos());
        for (int i = 0; i < days; i++) {
            param.setDateFrom(DateUtil.getInstence().convertDate(startDate));
            param.setDateTo(DateUtil.getInstence().convertDate(endDate));
            insertAchieveDayFreezeEnergy(param);
            startDate = endDate;
            endDate = DateUtils.addDays(startDate, 1);
        }
        logger.info("batchInsertFeeDetail end" + new Date());

    }
    //计算电量的方法
    //    @Override
//    public Double electricityConsumption(AchieveDayFreezeEnergyReq req) throws BusinessException {
//    	MeterData meterData = new MeterData();
//    	Date date = meterData.getUsedDate();
//    	int day = date.getDay();
//    	
//    }

    public void repairMeterData(RepairHydropoerDataReq req) throws BusinessException {
        //捕获有异常水的房间
        if (req.getDateFrom() == null) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REPAIR_HYDROPOWER_DATEFROM_IS_NULL);
        }
        if (req.getDateTo() == null) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REPAIR_HYDROPOWER_DATETO_IS_NULL);
        }

        int flag = 0;
        for (MeterTypeEnum meterType : MeterTypeEnum.values()) {
            req.setMeterType(meterType.getCode());
            //根据时间和枚举类型找出所有异常房间
            List<MeterData> aprtList = meterDataReadMapper.needRepairRoomList(req);
            if (aprtList != null && aprtList.size() > 0) {
                for (MeterData aprt : aprtList) {
                    req.setRoomId(aprt.getRoomId());
                    repairDataByAprt(req);
                }
                List<MeterData> resultList = meterDataReadMapper.needRepairRoomList(req);
                if (resultList != null && resultList.size() > 0) {
                    flag = 1;
                }
            }
        }

        if (flag == 1) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REPAIR_HYDROPOWER_METERTYPE_IS_SOME);
        }
    }

    private void repairDataByAprt(RepairHydropoerDataReq req) throws BusinessException {

        List<MeterData> meterDataList = meterDataReadMapper.queryWrongList(req);
        if (meterDataList == null && meterDataList.size() == 0) {
            return;
        }
        for (MeterData meterDate : meterDataList) {
            MeterData isSuccess = meterDataReadMapper.selectByPrimaryKey(meterDate.getId());
            if (isSuccess != null && isSuccess.getStatus() == 1) {
                continue;
            }
            MeterData detailUp = meterDataReadMapper.queryRightUp(meterDate);
            MeterData detailDown = meterDataReadMapper.queryRightDown(meterDate);
            if (detailUp == null) {
                logger.info("用户号" + meterDate.getRoomId() + "没有获得" + meterDate.getUsedDate() + "上一条正常数据");
                continue;
            }
            if (detailDown == null) {
                logger.info("用户号" + meterDate.getRoomId() + "没有获得" + meterDate.getUsedDate() + "上一条正常数据");
                continue;
            }
            AchieveDayFreezeEnergyReq realTimeEnergyReq = new AchieveDayFreezeEnergyReq();
            realTimeEnergyReq.setDateFrom(DateUtil.getInstence().convertDate(detailUp.getUsedDate()));
            realTimeEnergyReq.setDateTo(DateUtil.getInstence().convertDate(detailDown.getUsedDate()));
            realTimeEnergyReq.setMeterType(req.getMeterType());
            realTimeEnergyReq.setConsNos(String.valueOf(meterDate.getRoomId()));

            JSONObject resultObject = null;
            try {
                resultObject = JSONObject.fromObject(achieveDayFreezeEnergy(realTimeEnergyReq));
                JSONArray array = resultObject.getJSONArray("actionResult");
                JSONObject o1 = array.getJSONObject(0);
                Double totalFrom = Double.valueOf((String) o1.get("TOTAL_FROM"));
                Double totalTo = Double.valueOf((String) o1.get("TOTAL_TO"));
                if (detailUp.getTotalTo().compareTo(totalFrom) != 0) {
                    logger.info(o1.get("CONS_NO") + "的水止数据与接口的起始数据不一致！");
                    continue;
                }

                //修改用量
                int i = updateFeeDetail(resultObject, isSuccess.getRoomId(), realTimeEnergyReq.getDateTo(), req.getMeterType());
                RepairHydropoerDataReq params = new RepairHydropoerDataReq();

                //将区间内异常数据改为正常
                meterDataWriteMapper.updateWrongAprtStatus(realTimeEnergyReq);
            } catch (Exception e) {
                logger.info(meterDate.getRoomId() + "在重新获取" + DateUtil.getInstence().convertDate(detailDown.getUsedDate()) + "日数据异常");
                continue;
            }

        }
    }

    private void insertDayFreezeEnergy(JSONObject resultObject, Integer prjId) {

        JSONArray array = resultObject.getJSONArray("actionResult");
        for (int i = 0; array.size() > 0 && i < array.size(); i++) {
            JSONObject o1 = array.getJSONObject(i);
            MeterData meter = new MeterData();
            meter.setRoomId(Integer.valueOf((String) o1.get("CONS_NO")));
            //meter.setRoomId(11);
            meter.setPrjId(prjId);
            meter.setMeterType(Integer.valueOf((String) o1.get("METER_TYPE")));
            meter.setUsedDate(DateUtil.getInstence().convertDate((String) o1.get("DATE_TO")));
            Integer fdId = meterDataReadMapper.queryIdByParam(meter.getRoomId(),
                    DateUtil.getInstence().convertDate(meter.getUsedDate()), meter.getMeterType());
            if (fdId != null) {
                continue;
            }
            if (o1.get("MESSAGE") == null) {
                meter.setTotalFrom(new Double((String) o1.get("TOTAL_FROM")));
                meter.setTotalTo(new Double((String) o1.get("TOTAL_TO")));
                meter.setConsumption(new Double((String) o1.get("CONSUMPTION")));
                JSONArray changeList = (JSONArray) o1.get("rechangeMeterList");
                if (changeList != null && changeList.size() > 0) {
                    meter.setStatus(3);
                } else {
                    meter.setStatus(1);
                }
                meter.updateCommonInfo(-1);
                meterDataWriteMapper.insertSelective(meter);
                fdId = meter.getId();
                addChangeMeter(fdId, meter.getRoomId(), changeList, meter.getMeterType());
            } else {
                meter.setConsumption(new Double(0));
                meter.setTotalFrom(new Double(0));
                meter.setTotalTo(new Double(0));
                meter.setStatus(2);
                meter.setErrorMsg((String) resultObject.get("MESSAGE"));
                meter.updateCommonInfo(-1);
                meterDataWriteMapper.insertSelective(meter);
            }
            JSONArray changeList = (JSONArray) o1.get("rechangeMeterList");
        }
    }

    //新增换表记录
    private void addChangeMeter(Integer fdId, Integer aprtId, JSONArray changeList, Integer meterType) {
        try {
            if (changeList != null && changeList.size() > 0) {
                for (int i = 0; i < changeList.size(); i++) {
                    JSONObject o1 = changeList.getJSONObject(i);
                    ChangeMeter cm = new ChangeMeter();
                    //换表时间：YYYY-MM-DD HH:mm
                    cm.setChangeTime(DateUtil.getInstence().convertYMDHM((String) o1.get("TIME")));
                    //换表前表号
                    cm.setMeterId((String) o1.get("METERCOMID"));
                    //换表前总电能/累计流量
                    cm.setOldPower(Double.valueOf(o1.get("OLDPOWER").toString()));
                    //追补电量
                    cm.setZbPower(Double.valueOf(o1.get("ZBPOWER").toString()));
                    //换表后表号
                    cm.setNewMeterId((String) o1.get("NEWMETERCOMID"));
                    //换表后总电能/累计流量
                    cm.setNewPower(Double.valueOf(o1.get("NEWPOWER").toString()));
                    cm.setMeterType(meterType);
                    if (meterType.equals(VariableChar.elc_code)) {
                        ////换表后CT（仅电表有效）
                        cm.setNewCt((Integer) o1.get("NEWCT"));
                        ////换表后PT（仅电表有效）
                        cm.setNewPt((Integer) o1.get("NEWPT"));
                        //换表前CT（仅电表有效）
                        cm.setCt((Integer) o1.get("CT"));
                        //换表前PT（仅电表有效）
                        cm.setPt((Integer) o1.get("PT"));
                    }
                    cm.setAprtId(aprtId);
                    cm.setFeeDetailId(fdId);
                    cm.updateCommonInfo(0);
                    changeMeterWriteMapper.insertSelective(cm);
                }
            }
        } catch (Exception e) {

        }

    }


    public void checkObject(AchieveDayFreezeEnergyReq req) throws BusinessException {
        if (req.getConsNos() == null) {
            throw new BusinessException("用户编号不能为空");
        }

        if (req.getDateFrom() == null) {
            throw new BusinessException("开始日期不能为空");
        }

        if (req.getDateTo() == null) {
            throw new BusinessException("结束日期不能为空");
        }

        if (req.getMeterType() == null) {
            throw new BusinessException("类型不能为空");
        }
    }

    private int updateFeeDetail(Object object, Integer aprtId, String usedDate, Integer meterType) throws BusinessException {
        JSONObject resultObject = (JSONObject) object;
        int n = 0;
        JSONArray array = resultObject.getJSONArray("actionResult");
        if (array.size() > 0) {
            for (int i = 0; i < array.size(); i++) {
                JSONObject o1 = array.getJSONObject(i);
                MeterData meterData = new MeterData();
                meterData.setRoomId(11);
                meterData.setUsedDate(DateUtil.getInstence().convertDate(usedDate));
                meterData.setMeterType(meterType);
                if (o1.get("MESSAGE") == null) {
                    meterData.setConsumption(new Double((String) o1.get("CONSUMPTION")));
                    meterData.setTotalFrom(new Double((String) o1.get("TOTAL_FROM")));
                    meterData.setTotalTo(new Double((String) o1.get("TOTAL_TO")));
                    JSONArray changeList = (JSONArray) o1.get("rechangeMeterList");
                    if (changeList != null && changeList.size() > 0) {
                        meterData.setStatus(3);
                    } else {
                        meterData.setStatus(1);
                    }
                    meterData.setLastModifiedDtm(new Timestamp(new Date().getTime()));
                    meterData.setLastModifiedBy(-1);
                    Integer fdId = meterDataReadMapper.queryIdByParam(meterData.getRoomId(),
                            DateUtil.getInstence().convertDate(meterData.getUsedDate()), meterData.getMeterType());
                    n = meterDataWriteMapper.updateByPrimaryKeySelective(meterData);
                    //获取该条记录

                    //删除换表记录
                    changeMeterWriteMapper.deleteByFeeDetailId(fdId);
                    //重新添加换表记录
                    addChangeMeter(fdId, meterData.getRoomId(), changeList, meterType);
                } else {
                    throw new BusinessException(o1.get("MESSAGE") + "");
                }
            }
        }
        return n;
    }

    @Override
    public void cleanData() throws BusinessException
    {
        List<MeterData> meterDatas = meterDataReadMapper.selectCleanData();
        if (!meterDatas.isEmpty())
        {
            meterDataHistoryWriteMapper.cleanData();
            for (MeterData meterData : meterDatas)
            {
                meterDataWriteMapper.deleteByPrimaryKey(meterData.getId());
            }
        }
        else{
            throw new LandseaBusinessException(LandseaErrorMessageEnum.MeterData_Not_Exist);
        }
       
        
    }

    @Override
    public void saveCleanData(CleanLog log)
    {
        log.setType(2);
        log.setMessage("操作");
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        log.setIp(SysUtil.getClientIpAddr(request));
        log.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        cleanLogWriteMapper.insertSelective(log);
        
    }

    @Override
    public List<CleanLogDTO> selectCleanData()
    {
        List<CleanLogDTO> cleanLogDTOs = cleanLogReadMapper.selectCleanData();
        return cleanLogDTOs;
    }


}
